package com.carb.service.impl;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.carb.constant.MessageConstant;
import com.carb.context.UserContext;
import com.carb.dto.FeedbackPageQueryDTO;
import com.carb.dto.FeedbackUpdateDTO;
import com.carb.entity.*;
import com.carb.enums.BusinessStatus;
import com.carb.enums.FeedbackStatus;
import com.carb.enums.UserRole;
import com.carb.exception.BusinessErrorException;
import com.carb.exception.EntityNotFoundException;
import com.carb.mapper.*;
import com.carb.query.PageQueryUtils;
import com.carb.result.PageResult;
import com.carb.service.IFeedbackService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.carb.utils.RegexUtils;
import com.carb.vo.FeedbackVO;
import jakarta.annotation.Resource;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 评价管理 服务实现类
 * </p>
 *
 * @author XuChaoyang
 * @since 2025-01-18
 */
@Service
public class FeedbackServiceImpl extends ServiceImpl<FeedbackMapper, Feedback> implements IFeedbackService {

    @Resource
    private ProjectMapper projectMapper;

    @Resource
    private UserMapper userMapper;

    @Resource
    private EmployeeMapper employeeMapper;

    @Resource
    private MemberMapper memberMapper;

    @Resource
    private CarMapper carMapper;

    @Resource
    private BusinessMapper businessMapper;

    /**
     * 评价分页查询
     * @param feedbackPageQueryDTO 查询条件
     * @return 评价分页结果
     */
    @Override
    public PageResult<Feedback> pageQuery(FeedbackPageQueryDTO feedbackPageQueryDTO) {
        // 1、获取查询属性
        // 1.1、分页属性
        Long pageNum = PageQueryUtils.checkPageNum(feedbackPageQueryDTO.getPageNum());
        Long pageSize = PageQueryUtils.checkPageSize(feedbackPageQueryDTO.getPageSize());
        String orderBy = feedbackPageQueryDTO.getOrderBy();
        Boolean isAsc = feedbackPageQueryDTO.getIsAsc();
        // 1.2、查询属性
        String projectName = feedbackPageQueryDTO.getProjectName();
        Long projectTypeId = feedbackPageQueryDTO.getProjectTypeId();
        String employeeName = feedbackPageQueryDTO.getEmployeeName();
        String memberName = feedbackPageQueryDTO.getMemberName();
        String plateNumber = feedbackPageQueryDTO.getPlateNumber();

        // 2、构建条件
        // 2.1、分页条件
        Page<Feedback> page = Page.of(pageNum, pageSize);
        // 2.2、排序条件
        PageQueryUtils.applySorting(page, orderBy, isAsc);
        // 2.3、空结果
        PageResult<Feedback> emptyPageResult = new PageResult<>(page.getTotal(), page.getPages(), Collections.emptyList());

        // 3、根据服务项目名称+服务项目类型id（不同时为空），得到服务项目id集合
        List<Long> projectIdList = null;
        if (projectName != null || projectTypeId != null) {
            projectIdList = projectMapper.getProjectIdsByProjectNameOrType(projectName, projectTypeId);
            if (projectIdList.isEmpty()) return emptyPageResult;
        }

        // 4、根据员工姓名（不为空），得到员工id集合
        List<Long> employeeIdList = null;
        if (employeeName != null) {
            // 根据员工姓名查询员工的用户id
            List<Long> employeeUserIdList = userMapper.getUserIdsByName(employeeName, UserRole.EMPLOYEE);
            if (employeeUserIdList.isEmpty()) return emptyPageResult;
            // 根据员工的用户id查询员工id
            employeeIdList = employeeMapper.getEmployeeIdsByUserIds(employeeUserIdList);
            if (employeeIdList.isEmpty()) return emptyPageResult;
        }

        // 5、根据会员姓名（不为空），得到会员id集合
        List<Long> memberIdList = null;
        if (memberName != null) {
            // 根据会员姓名查询会员的用户id
            List<Long> memberUserIdList = userMapper.getUserIdsByName(memberName, UserRole.MEMBER);
            if (memberUserIdList.isEmpty()) return emptyPageResult;
            // 根据会员的用户id查询会员id
            memberIdList = memberMapper.getMemberIdsByUserIds(memberUserIdList);
            if (memberIdList.isEmpty()) return emptyPageResult;
        }

        // 6、根据车牌号（不为空），得到车辆id集合
        List<Long> carIdList = null;
        if (plateNumber != null) {
            carIdList = carMapper.getCarIdsByPlateNumber(plateNumber);
            if (carIdList.isEmpty()) return emptyPageResult;
        }

        // 7、业务表查询，得到业务id
        List<Long> businessIdList = businessMapper.getBusinessIdsByList(projectIdList, employeeIdList, memberIdList, carIdList);
        if (businessIdList.isEmpty()) return emptyPageResult;

        // 8、评价表查询（业务id）
        Page<Feedback> feedbackPage = this.page(page, Wrappers.lambdaQuery(Feedback.class)
                .in(Feedback::getBusinessId, businessIdList)
                .ne(Feedback::getStatus, FeedbackStatus.FORBID_FEEDBACK));

        // 9、返回封装结果
        return new PageResult<>(feedbackPage.getTotal(), feedbackPage.getPages(), feedbackPage.getRecords());
    }

    /**
     * 根据评价id查询评价信息
     * @param id 评价id
     * @return 查询结果
     */
    @Override
    public Feedback getFeedbackById(Long id) {
        Feedback feedback = this.getById(id);
        if (feedback == null) {
            // 评价不存在
            throw new EntityNotFoundException(MessageConstant.FEEDBACK_NOT_FOUND);
        }
        return feedback;
    }

    /**
     * 会员提交评价
     * @param feedbackUpdateDTO 会员提交的评价信息
     */
    @Override
    @Transactional
    public void updateFeedback(FeedbackUpdateDTO feedbackUpdateDTO) {
        // 1、检查评价是否存在
        Long feedbackId = feedbackUpdateDTO.getId();
        if (feedbackId == null) {
            throw new EntityNotFoundException(MessageConstant.FEEDBACK_NOT_FOUND);
        }

        // 2、检查是否待评价
        Feedback feedback = this.getById(feedbackId);
        if (feedback.getStatus() == FeedbackStatus.FORBID_FEEDBACK) {
            // 业务未完成，不可评价
            throw new BusinessErrorException(MessageConstant.BUSINESS_INCOMPLETE + MessageConstant.CAN_NOT_FEEDBACK);
        }
        if (feedback.getStatus() == FeedbackStatus.ALREADY_FEEDBACK) {
            // 已评价，不可再评价
            throw new BusinessErrorException(MessageConstant.ALREADY_FEEDBACK + MessageConstant.CAN_NOT_FEEDBACK);
        }

        // 3、评分需要进行正则校验
        RegexUtils.checkRating(feedbackUpdateDTO.getRating().toString());

        // 4、更新评价
        this.update(new Feedback(), Wrappers.lambdaUpdate(Feedback.class)
                .eq(Feedback::getId, feedbackId)
                .set(Feedback::getRating, feedbackUpdateDTO.getRating())
                .set(Feedback::getContent, feedbackUpdateDTO.getContent())
                .set(Feedback::getStatus, FeedbackStatus.ALREADY_FEEDBACK));
    }

    /**
     * 会员自身待评价数量查询
     * @return 待评价数量
     */
    @Override
    public Long countFeedbackForMember() {
        // 1、获取当前登录会员id
        Long userId = UserContext.getUserId();
        Long memberId = memberMapper.getMemberIdsByUserIds(List.of(userId)).getFirst();

        // 2、查询业务ids
        List<Long> businessIds = businessMapper.selectList(Wrappers.lambdaQuery(Business.class)
                        .eq(Business::getMemberId, memberId)
                        .eq(Business::getStatus, BusinessStatus.COMPLETED))
                .stream().map(Business::getId).toList();
        if (businessIds.isEmpty()) return 0L;

        // 3、查询并返回待评价数量
        return this.count(Wrappers.lambdaQuery(Feedback.class)
                .in(Feedback::getBusinessId, businessIds)
                .eq(Feedback::getStatus, FeedbackStatus.WAIT_FEEDBACK));
    }

    /**
     * 会员自身评价查询
     * @param feedbackStatus 评价状态
     * @return 评价列表
     */
    @Override
    public List<FeedbackVO> listFeedbackForMember(FeedbackStatus feedbackStatus) {
        // 1、获取当前登录会员id
        Long userId = UserContext.getUserId();
        Long memberId = memberMapper.getMemberIdsByUserIds(List.of(userId)).getFirst();

        // 2、获取业务Map（id-business）
        Map<Long, Business> businessMap = businessMapper.selectList(Wrappers.lambdaQuery(Business.class)
                        .eq(Business::getMemberId, memberId)).stream()
                .collect(Collectors.toMap(Business::getId, business -> business));
        if (businessMap.isEmpty()) return Collections.emptyList();

        // 3、获取评价列表
        List<Feedback> feedbackList = this.list(Wrappers.lambdaQuery(Feedback.class)
                .in(Feedback::getBusinessId, businessMap.keySet())
                .eq(Feedback::getStatus, feedbackStatus)
                .orderByDesc(Feedback::getUpdateTime));

        // 4、封装VO
        List<FeedbackVO> feedbackVOList = new ArrayList<>();
        for (Feedback feedback : feedbackList) {
            FeedbackVO feedbackVO = new FeedbackVO();
            BeanUtils.copyProperties(feedback, feedbackVO);
            feedbackVO.setProjectName(projectMapper.selectById(businessMap.get(feedback.getBusinessId()).getProjectId()).getName())
                    .setEmployeeName(employeeMapper.getNameByEmployeeId(businessMap.get(feedback.getBusinessId()).getEmployeeId()))
                    .setCarPlateNumber(carMapper.selectById(businessMap.get(feedback.getBusinessId()).getCarId()).getPlateNumber());
            feedbackVOList.add(feedbackVO);
        }

        // 5、返回封装结果
        return feedbackVOList;
    }

}
